/*
** 5200Sys.c
** 5200 specific part of the disassembler.
*/

#include <windows.h>
#include <windowsx.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include "..\compusys.h"

#define ATARI_FONT "5200.FON"

HINSTANCE hDllInst;
char szDllPath[_MAX_PATH];
char szFontPath[_MAX_PATH];

/*
** allocate global memory
*/
static BYTE *MemoryAlloc(WORD wSize)
{
     return GlobalAllocPtr(GHND, (DWORD) wSize);
}

/*
** resize global memory
*/
static BYTE *MemoryRealloc(BYTE *lpBuf, WORD wSize)
{
     return GlobalReAllocPtr(lpBuf, (DWORD) wSize, GMEM_MOVEABLE);
}

/*
** free global memory
*/
static void MemoryFree(BYTE *lpBuf)
{
     GlobalFreePtr(lpBuf);
}

/*
** declare Atari font
*/
BOOL CALLBACK __export CompuInit(HINSTANCE hInst)
{
char *szSlash;

     /*
     ** Load font.
     */
     GetModuleFileName(hDllInst, szDllPath, sizeof(szDllPath));
     strcpy(szFontPath, szDllPath);
     if (szSlash = strrchr(szFontPath, '\\'))
          strcpy(szSlash + 1, ATARI_FONT);
     else strcpy(szFontPath, ATARI_FONT);
     if (! AddFontResource(szFontPath))
          return FALSE;

     /*
     ** if the font loaded successfully, notify other applications.
     */
     SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
     return TRUE;
}

/*
** remove Atari font.
*/
void CALLBACK __export CompuTerm(void)
{
     RemoveFontResource(szFontPath);
     SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
}

/*
** retruns the menu item available
*/
WORD CALLBACK __export CompuGetMenu(void)
{
     return MENU_BINARY_FILE;
}

/*
** load a segment from a binary file
*/
BOOL CALLBACK __export CompuLoadSegment(int fd, SEGMENT *lpSeg, BOOL bReadType)
{
WORD wSize;

     /*
     ** get segment size.
     */
     wSize = lpSeg->wEnd - lpSeg->wBegin + 1;

     /*
     ** allocate memory for data and for byte type.
     */
     lpSeg->lpDump = MemoryAlloc(wSize);
     if (lpSeg->lpDump == NULL)
          return FALSE;
     lpSeg->lpType = MemoryAlloc(wSize);
     if (lpSeg->lpType == NULL)
          {
          MemoryFree(lpSeg->lpDump);
          lpSeg->lpDump = NULL;
          return FALSE;
          }

     /*
     ** read segment from file.
     */
     if ((WORD) read(fd, lpSeg->lpDump, wSize) != wSize)
          return FALSE;
     if (bReadType)
          if ((WORD) read(fd, lpSeg->lpType, wSize) != wSize)
               return FALSE;
     return TRUE;
}

/*
** send segment description to segment listbox.
*/
BOOL CALLBACK __export CompuUpdateSegment(HWND hSegmentList, SEGMENT *lpSeg)
{
char szBuf[80];
DWORD dwIndex;

     wsprintf(szBuf, "$%04X-$%04X:%u ($%04X)", lpSeg->wBegin, lpSeg->wEnd, lpSeg->wEnd - lpSeg->wBegin + 1, lpSeg->wEnd - lpSeg->wBegin + 1);
     dwIndex = SendMessage(hSegmentList, LB_ADDSTRING, 0, (LPARAM) (LPCSTR) szBuf);
     return (dwIndex != LB_ERR);
}

/*
** read an Atari binary file.
*/
BOOL CALLBACK __export CompuReadFile(HWND hSegmentList, int fd, SEGMENT *Segment, int nFirstSeg)
{
WORD wSize;
char szBuf[80];
long lFileLength;
DWORD dwIndex;
int i;
unsigned char cChar;

     /*
     ** Check that the file length is less than 32K.
     */
     lFileLength = filelength(fd);
     if (lFileLength > 32768L)
          return FALSE;

     /*
     ** read segment data.
     */
     Segment[nFirstSeg].wBegin = (WORD) ((DWORD) 0xC000 - (DWORD) lFileLength);
     Segment[nFirstSeg].wEnd = 0xBFFF;
     Segment[nFirstSeg].bBinary = TRUE;
     wSize = Segment[nFirstSeg].wEnd - Segment[nFirstSeg].wBegin + 1;
     CompuLoadSegment(fd, &Segment[nFirstSeg], FALSE);

     /*
     ** extract title from data and convert it to ASCII
     */
     memcpy(Segment[nFirstSeg].szTitle, Segment[nFirstSeg].lpDump + lFileLength - 24, 20);
     Segment[nFirstSeg].szTitle[20] = 0;
     for (i = 0; i < 20; i++)
          {
          cChar = (unsigned char) Segment[nFirstSeg].szTitle[i];
          if (cChar < 64)
               cChar += 32;
          else if (cChar < 96)
               cChar -= 64;
          else if ((cChar >= 128) && (cChar < 128 + 64))
               cChar += 32;
          else if ((cChar >= 128 + 64) && (cChar < 128 + 96))
               cChar -= 64;
          Segment[nFirstSeg].szTitle[i] = (char) cChar;
          }
     for (i = 0; i < 20; i++)
          if (Segment[nFirstSeg].szTitle[i] != 0 && Segment[nFirstSeg].szTitle[i] != ' ')
               break;
     if (i != 0)
          {
          memmove(Segment[nFirstSeg].szTitle, &Segment[nFirstSeg].szTitle[i], 20 - i);
          Segment[nFirstSeg].szTitle[20 - i] = 0;
          }
     for (; i > 0; i--)
          if (Segment[nFirstSeg].szTitle[i] == ' ')
               Segment[nFirstSeg].szTitle[i] = 0;

     /*
     ** add this segment to the segment list.
     */
     wsprintf(szBuf, "$%04X-$%04X:%u \"%s\"", Segment[nFirstSeg].wBegin, Segment[nFirstSeg].wEnd, wSize, Segment[nFirstSeg].szTitle);
     dwIndex = SendMessage(hSegmentList, LB_ADDSTRING, 0, (LPARAM) (LPCSTR) szBuf);
     return dwIndex != LB_ERR;
}

/*
** Value of return.
*/
BYTE CALLBACK __export CompuGetReturn(void)
{
     return 0x9B;
}

/*
** DLL entry point
*/
BOOL CALLBACK LibMain(HINSTANCE hinst, UINT wDS, UINT cbHeap, DWORD unused)
{
     hDllInst = hinst;
     return TRUE;
}

/*
** DLL exit point
*/
int FAR PASCAL _WEP(int unused)
{
     return TRUE;
}
